from django.contrib.auth import login, logout
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.forms import PasswordChangeForm, AuthenticationForm
from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION
from django.contrib.contenttypes.models import ContentType
from django.http import HttpResponseRedirect, HttpResponse
from django.core.paginator import Paginator
from django.views.generic import ListView, DetailView, CreateView, UpdateView
from django.views.decorators.http import require_http_methods
from django.db.models.functions import TruncMonth
from django.db.models import Count, Q
from django.utils.translation import gettext_lazy as _
from django.template.loader import render_to_string
from django.conf import settings
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import ImproperlyConfigured
import weasyprint
from .utils import convert_num_to_chinese, convert_list
import json
import re
from antcook import sms_aliyun
from .forms import *
import xlwt
from io import BytesIO
import datetime


app_name = GeneralConfig.name
mobile_ls = GeneralConfig.mobile_ls


def validate_date(date_text):
    if not date_text:
        return False
    try:
        date_reg_exp_1 = re.compile('\d{4}[-/]\d{1,2}[-/]\d{1,2}')
        matches_list = date_reg_exp_1.findall(date_text)
        if matches_list:
            date_text = matches_list[0].replace('/', '-')
            date_text = datetime.datetime.strptime(date_text, "%Y-%m-%d").strftime('%Y-%m-%d')
            return date_text
    except ValueError:
        return False
        # raise ValueError("错误是日期格式或日期,格式是年-月-日")


def outcome_by_types_pie(outcomes=None):
    if not outcomes:
        outcomes = InOut.objects.filter(is_confirmed=True)
    outcome_by_types = list()
    for t in InOutType.objects.filter(is_out=True):
        o_p = outcomes.filter(in_out_type_id=t.pk).annotate(mio=Sum('amount')).values('mio')
        if o_p:
            mio = 0
            for sss in o_p:
                mio += float(sss['mio'])
            outcome_by_types.append(['{0}'.format(t.in_out_type), - mio])
    return outcome_by_types


def io_per_month_column():
    io_per_month = None
    in_out_month = list()
    income_info = list()
    total_income = 0
    total_outcome = 0
    outcome_info = list()
    io_come_info = list()
    month_l = list()
    money_in_out = InOut.objects.exclude(
        in_out_date__isnull=True).filter(is_confirmed=True)
    if money_in_out:
        io_per_month = money_in_out.annotate(
            month=TruncMonth('in_out_date')).annotate(sum=Sum('amount')).values(
            'month', 'sum').order_by('month')
    if io_per_month:
        for opm in io_per_month:
            if opm['month'] not in month_l:
                in_out_month.append('{0}'.format(opm['month'].strftime("%Y-%m")))
                io_come_info.append(float(opm['sum']))
                if float(opm['sum']) > 0:
                    income_info.append(float(opm['sum']))
                    outcome_info.append(0)
                    total_income += float(opm['sum'])
                else:
                    income_info.append(0)
                    outcome_info.append(float(opm['sum']))
                    total_outcome += float(opm['sum'])
                month_l.append(opm['month'])
            else:
                io_come_info[-1] += float(opm['sum'])
                if float(opm['sum']) > 0:
                    income_info[-1] += float(opm['sum'])
                    total_income += float(opm['sum'])
                else:
                    outcome_info[-1] += float(opm['sum'])
                    total_outcome += float(opm['sum'])
    return [in_out_month, income_info, outcome_info, io_come_info, total_income, total_outcome]


def get_content_type_for_model(obj):
    from django.contrib.contenttypes.models import ContentType
    return ContentType.objects.get_for_model(obj, for_concrete_model=False)


def send_msg(name=None, new_order=None, m_ls=mobile_ls):
    if m_ls and name and new_order:
        params = str({'name': name, 'new_order': new_order})
        for m in m_ls:
            if re.match(r'1[3,4,5,7,8]\d{9}', m):
                rsp = sms_aliyun.sms_aliyun_url(mobile=m, template_code="SMS_146805385", para=params)
                print(rsp)


def render_to_pdf_response(request=None, template_name=None, context=None, filename=None):
    if request:
        html = render_to_string(template_name, context)
        pdf_file = weasyprint.HTML(
            string=html,
            base_url=request.build_absolute_uri()
        ).write_pdf(
            stylesheets=[weasyprint.CSS(str(settings.STATIC_ROOT) + '/{0}/css/{0}-pdf.css'.format(app_name))]
        )
        http_response = HttpResponse(pdf_file, content_type='application/pdf')
        if not filename:
            filename = 'generated_file'
        http_response['Content-Disposition'] = 'filename={0}'.format(filename)
        return http_response


def tb_login(request):
    template_name = 'registration/login.html'
    redirect_to = 'public'
    if request.method == 'POST':
        form = AuthenticationForm(data=request.POST)
        if form.is_valid():
            user = form.get_user()
            login(request, user)
        if 'next' in request.POST:
            return redirect(request.POST.get('next'))
        else:
            return redirect(redirect_to)
    else:
        form = AuthenticationForm()
    return render(request, template_name=template_name, context={'form': form})


def tb_logout(request):
    redirect_to = 'public'
    logout(request)
    return redirect(redirect_to)


class TechBrewListView(PermissionRequiredMixin, ListView):
    paginate_by = 20

    @staticmethod
    def get_required_object_permissions(model_cls):
        return '{0}.view_{1}'.format(getattr(model_cls, '_meta').app_label, getattr(model_cls, '_meta').model_name)

    def get_permission_required(self):
        if self.permission_required is None:
            if self.model is None:
                raise ImproperlyConfigured(
                    '{0} is missing the model attribute.'.format(self.__class__.__name__)
                )
            else:
                self.permission_required = self.get_required_object_permissions(self.model)
        if isinstance(self.permission_required, str):
            perms = (self.permission_required,)
        else:
            perms = self.permission_required
        return perms


class TechBrewDetailView(PermissionRequiredMixin, DetailView):

    @staticmethod
    def get_required_object_permissions(model_cls):
        return '{0}.view_{1}'.format(getattr(model_cls, '_meta').app_label, getattr(model_cls, '_meta').model_name)

    def get_permission_required(self):
        if self.permission_required is None:
            if self.model is None:
                raise ImproperlyConfigured(
                    '{0} is missing the model attribute.'.format(self.__class__.__name__)
                )
            else:
                self.permission_required = self.get_required_object_permissions(self.model)
        if isinstance(self.permission_required, str):
            perms = (self.permission_required,)
        else:
            perms = self.permission_required
        return perms


class TechBrewCreateView(PermissionRequiredMixin, CreateView):

    @staticmethod
    def get_required_object_permissions(model_cls):
        return '{0}.add_{1}'.format(getattr(model_cls, '_meta').app_label, getattr(model_cls, '_meta').model_name)

    def get_permission_required(self):
        if self.permission_required is None:
            if self.model is None:
                raise ImproperlyConfigured(
                    '{0} is missing the model attribute.'.format(self.__class__.__name__)
                )
            else:
                self.permission_required = self.get_required_object_permissions(self.model)
        if isinstance(self.permission_required, str):
            perms = (self.permission_required,)
        else:
            perms = self.permission_required
        return perms

    def get_success_url(self):
        if self.request.GET:
            if self.request.GET.get('next'):
                return self.request.GET.get('next')
        return super().get_success_url()

    def form_valid(self, form):
        if form.is_valid:
            model = form.save(commit=False)
            model.save()
            if model:
                LogEntry.objects.log_action(
                    user_id=self.request.user.pk,
                    content_type_id=get_content_type_for_model(model).pk,
                    object_id=model.pk,
                    object_repr=str(model),
                    action_flag=ADDITION,
                )
        return super().form_valid(form)


class TechBrewUpdateView(PermissionRequiredMixin, UpdateView):

    @staticmethod
    def get_required_object_permissions(model_cls):
        return '{0}.change_{1}'.format(getattr(model_cls, '_meta').app_label, getattr(model_cls, '_meta').model_name)

    def get_permission_required(self):
        if self.permission_required is None:
            if self.model is None:
                raise ImproperlyConfigured(
                    '{0} is missing the model attribute.'.format(self.__class__.__name__)
                )
            else:
                self.permission_required = self.get_required_object_permissions(self.model)
        if isinstance(self.permission_required, str):
            perms = (self.permission_required,)
        else:
            perms = self.permission_required
        return perms

    def get_success_url(self):
        if self.request.GET:
            if self.request.GET.get('next'):
                return self.request.GET.get('next')
        return super().get_success_url()

    def form_valid(self, form):
        if form.is_valid:
            model = form.save(commit=False)
            model.save()
            if model:
                LogEntry.objects.log_action(
                    user_id=self.request.user.pk,
                    content_type_id=get_content_type_for_model(model).pk,
                    object_id=model.pk,
                    object_repr=str(model),
                    action_flag=CHANGE,
                )
        return super().form_valid(form)


def object_paginator(request, object_list, per_page_count=50):
    paginator = Paginator(object_list, per_page_count)
    page = request.GET.get('page', 1)
    data = paginator.get_page(page)
    return data


@login_required
@permission_required('{0}.view_order'.format(app_name))
def home_overview(request):
    template_name = '{0}/overview.html'.format(app_name)
    list_3 = ['tt', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 's1', 's2', 's3', 's4', 's5', 's6']
    order_info_1 = list()
    order_info_2 = list()
    order_info_3 = dict()
    order_info_3['name'] = list()
    for l in list_3:
        order_info_3[l] = list()
    month_l = list()
    order_state_n = list()
    context = dict()

    order_states = OrderState.objects.all().order_by('id')
    all_orders = Order.objects.all()

    if all_orders.exists():
        order_per_month = Order.objects.annotate(
            month=TruncMonth('datetime_created')).annotate(
            tt=Count('id')).annotate(
            c1=Count('id', filter=Q(order_state=1))).annotate(
            c2=Count('id', filter=Q(order_state=2))).annotate(
            c3=Count('id', filter=Q(order_state=3))).annotate(
            c4=Count('id', filter=Q(order_state=4))).annotate(
            c5=Count('id', filter=Q(order_state=5))).annotate(
            c6=Count('id', filter=Q(order_state=6))).annotate(
            s1=Sum('price_all_final', filter=Q(order_state=1))).annotate(
            s2=Sum('price_all_final', filter=Q(order_state=2))).annotate(
            s3=Sum('price_all_final', filter=Q(order_state=3))).annotate(
            s4=Sum('price_all_final', filter=Q(order_state=4))).annotate(
            s5=Sum('price_all_final', filter=Q(order_state=5))).annotate(
            s6=Sum('price_all_final', filter=Q(order_state=6))
        ).values(
            'month', 'tt', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 's1', 's2', 's3', 's4', 's5', 's6').order_by('month')
        for opm in order_per_month:
            if opm['month'] not in month_l:
                order_info_3['name'].append('{0}'.format(opm['month'].strftime("%Y-%m")))
                for l in list_3:
                    if opm[l]:
                        order_info_3[l].append(float(round(opm.get(l), 2)))
                    else:
                        order_info_3[l].append(0)
                month_l.append(opm['month'])
            else:
                for l in list_3:
                    if opm[l]:
                        order_info_3[l][-1] += float(round(opm[l], 2))

    if order_states.exists():
        for o_s in order_states:
            order_state_n.append(o_s.order_state_cn)
            order_info_1.append(
                [o_s.order_state_cn, Order.objects.filter(order_state_id=o_s.pk).count()])
    salesmen = Salesman.objects.all()
    if salesmen.exists():
        for s_m in salesmen:
            order_info_2.append(
                [s_m.name, Order.objects.filter(salesman_id=s_m.pk).count()])

    context['u'] = User.objects.filter(Q(
        user_permissions__content_type__app_label=app_name) | Q(
        groups__permissions__content_type__app_label=app_name)).filter(
        is_active=True).distinct().order_by('-last_login')
    context['a'] = Announce.objects.filter(is_show=True)[:5]
    context['order_info_1'] = json.dumps(order_info_1)
    context['order_info_2'] = json.dumps(order_info_2)
    context['order_info_3_x'] = json.dumps(order_info_3['name'])
    context['order_info_3_y'] = json.dumps(order_info_3['tt'])
    if order_states.count():
        for x in range(1, 7):
            context['order_info_3_x{0}'.format(x)] = json.dumps(order_state_n[x-1])
            context['order_info_3_y{0}'.format(x)] = json.dumps(order_info_3['c{0}'.format(x)])
            context['order_info_3_z{0}'.format(x)] = json.dumps(order_info_3['s{0}'.format(x)])
    return render(request, template_name=template_name, context=context)


def order_info_price(pk):
    if pk:
        pk = int(str(pk).replace(',', ''))
    order_info = get_object_or_404(Order, pk=pk)
    order_item_list = ItemList.objects.filter(order_id=pk).order_by('order_index', 'datetime_created')
    total_price = 0  # 人民币总价
    total_price_auto = 0  # 设定币种总价
    total_discount = 0  # 人民币总折扣
    total_discount_auto = 0  # 设定币种总折扣
    if order_item_list.exists():
        for item in order_item_list:
            if item.initial_price_each:  # 如果销售员提供自定义报价
                if item.equipment.dist_price:  # 如果设备有工厂底价, 判断设备的报价是否低于底价，低于工厂底价则无效
                    if item.initial_price_each < item.equipment.dist_price:
                        ItemList.objects.filter(pk=item.id).update(initial_price_each=item.equipment.basic_price)
            else:  # 如果销售员没有提供报价
                ItemList.objects.filter(pk=item.id).update(initial_price_each=item.equipment.basic_price)
            if item.item_total_price:
                total_price += float(item.item_total_price)
            if item.item_total_price_auto:
                total_price_auto += float(item.item_total_price_auto)
            if item.item_total_discount:
                total_discount += float(item.item_total_discount)
            if item.item_total_discount_auto:
                total_discount_auto += float(item.item_total_discount_auto)
    if order_info.transport_cost:
        total_price += float(order_info.transport_cost)
    if order_info.install_cost:
        total_price += float(order_info.install_cost)
    if order_info.material_cost:
        total_price += float(order_info.material_cost)
    if order_info.transport_cost_auto:
        total_price_auto += float(order_info.transport_cost_auto)
    if order_info.install_cost_auto:
        total_price_auto += float(order_info.install_cost_auto)
    if order_info.material_cost_auto:
        total_price_auto += float(order_info.material_cost_auto)
    price_without_tax = total_price - total_discount
    price_without_tax_auto = total_price_auto - total_discount_auto
    price_tax = 0
    price_tax_auto = 0
    extra_discount = 0
    extra_discount_auto = 0
    if order_info.tax_rate:
        order_info_tax_rate = float(order_info.tax_rate)
    else:
        order_info_tax_rate = 0
    if order_info.need_to_pay:
        price_with_tax = float(order_info.need_to_pay)
        price_tax = round(price_with_tax - price_with_tax/(100 + order_info_tax_rate) * 100, 2)
        extra_discount = - (price_with_tax - price_tax - price_without_tax)
        price_with_tax_auto = price_with_tax
        price_tax_auto = price_tax
        extra_discount_auto = extra_discount
        if order_info.export_price:
            if order_info.export_price.export_price_rate:
                price_with_tax_auto = round(price_with_tax / float(order_info.export_price.export_price_rate), 2)
                price_tax_auto = round(price_with_tax_auto - price_with_tax_auto/(100 + order_info_tax_rate) * 100, 2)
                extra_discount_auto = - (price_with_tax_auto - price_tax_auto - price_without_tax_auto)
    else:
        if order_info.tax_rate:
            price_tax = round(price_without_tax * order_info_tax_rate / 100, 2)
            price_tax_auto = price_tax
            if order_info.export_price:
                if order_info.export_price.export_price_rate:
                    price_tax_auto = round(price_tax / float(order_info.export_price.export_price_rate), 2)
        price_with_tax = price_tax + price_without_tax
        price_with_tax_auto = price_tax_auto + price_without_tax_auto
    c_price_with_tax = convert_num_to_chinese(price_with_tax)
    Order.objects.filter(id=pk).update(
        total_price=total_price, total_discount=total_discount, price_all_final=price_with_tax)
    return {'order_info': order_info,  # 订单信息
            'item_list': order_item_list,  # 设备清单
            'total_price': round(total_price, 2),  # 折扣前总价
            'total_price_auto': round(total_price_auto, 2),  # 折扣前总价
            'total_discount': round(total_discount, 2),  # 设备总折扣
            'total_discount_auto': round(total_discount_auto, 2),  # 设备总折扣
            'extra_discount': round(extra_discount, 2),  # 额外折扣
            'extra_discount_auto':  round(extra_discount_auto, 2),  # 额外折扣
            'extra_total_discount': round(extra_discount + total_discount, 2),  # 额外折扣 + 设备总折扣
            'extra_total_discount_auto': round(extra_discount_auto + total_discount_auto, 2),  # 额外折扣 + 设备总折扣
            'price_tax': round(price_tax, 2),  # 税收
            'price_tax_auto': round(price_tax_auto, 2),  # 税收
            'price_with_tax': round(price_with_tax, 2),  # 含税总价数字
            'price_with_tax_auto': round(price_with_tax_auto, 2),  # 含税总价数字
            'c_price_with_tax': c_price_with_tax,  # 含税总价中文
            'price_without_tax': round(price_without_tax, 2),
            'price_without_tax_auto': round(price_without_tax_auto, 2),
            'print_date': timezone.datetime.today,
            }


def public_order_quotation(request, order_public_access_key, pk):
    if pk:
        pk = int(str(pk).replace(',', ''))
    order_info = get_object_or_404(Order, pk=pk)
    template = '{0}/order/order_quotation.html'.format(app_name)
    context = order_info_price(order_info.pk)
    if order_info:
        if order_info.order_key == order_public_access_key:
            if request.GET.get('v') == 'pdf':
                return render_to_pdf_response(request, template_name=template, context=context,
                                              filename='{0}_quotation_cn.pdf'.format(order_info.order_code))
            return render(request, template_name=template, context=context)
    return HttpResponseRedirect(reverse('public'))


def public_order_quotation_old(request, order_public_access_key, pk):
    if pk:
        pk = int(str(pk).replace(',', ''))
    order_info = get_object_or_404(Order, pk=pk)
    if order_info and request:
        if order_info.order_key == order_public_access_key:
            return redirect('{0}:public_order_quotation'.format(app_name),
                            order_public_access_key=order_public_access_key, pk=pk)
    return HttpResponseRedirect(reverse('public'))


def public_order_quotation_en(request, order_public_access_key, pk):
    if pk:
        pk = int(str(pk).replace(',', ''))
    order_info = get_object_or_404(Order, pk=pk)
    template = '{0}/order/order_quotation_en.html'.format(app_name)
    context = order_info_price(order_info.pk)
    if order_info:
        if order_info.order_key == order_public_access_key:
            if request.GET.get('v') == 'pdf':
                return render_to_pdf_response(request, template_name=template, context=context,
                                              filename='{0}_quotation_en.pdf'.format(order_info.order_code))
            return render(request, template_name=template, context=context)
    return HttpResponseRedirect(reverse('public'))


@login_required
@permission_required('{0}.view_order'.format(app_name))
def order_contract_cn(request, pk):
    if pk:
        pk = int(str(pk).replace(',', ''))
    template = '{0}/order/order_contract_cn.html'.format(app_name)
    context = order_info_price(pk)
    order_info = get_object_or_404(Order, pk=pk)
    if order_info:
        if request.user.is_staff or request.user.has_perm('{0}.view_all_orders'.format(app_name)) or \
                request.user.pk == order_info.created_by_id:
            if request.GET.get('v') == 'pdf':
                return render_to_pdf_response(request, template_name=template, context=context,
                                              filename='{0}_contract_cn.pdf'.format(order_info.order_code))
            return render(request, template_name=template, context=context)
    return HttpResponseRedirect(reverse('public'))


@login_required
@permission_required('{0}.view_order'.format(app_name))
def order_contract_en(request, pk):
    if pk:
        pk = int(str(pk).replace(',', ''))
    template = '{0}/order/order_contract_en.html'.format(app_name)
    context = order_info_price(pk)
    order_info = get_object_or_404(Order, pk=pk)
    if order_info:
        if request.user.is_staff or request.user.has_perm('{0}.view_all_orders'.format(app_name)) or \
                request.user.pk == order_info.created_by_id:
            if request.GET.get('v') == 'pdf':
                return render_to_pdf_response(request, template_name=template, context=context,
                                              filename='{0}_contract_en.pdf'.format(order_info.order_code))
            return render(request, template_name=template, context=context)
    return HttpResponseRedirect(reverse('public'))


@login_required
@permission_required('{0}.view_order'.format(app_name))
def order_invoice_en(request, pk):
    if pk:
        pk = int(str(pk).replace(',', ''))
    template = '{0}/order/order_invoice_en.html'.format(app_name)
    context = order_info_price(pk)
    order_info = get_object_or_404(Order, pk=pk)
    if order_info:
        if request.user.is_staff or request.user.has_perm('{0}.view_all_orders'.format(app_name)) or \
                request.user.pk == order_info.created_by_id:
            if request.GET.get('v') == 'pdf':
                return render_to_pdf_response(request, template_name=template, context=context,
                                              filename='{0}_invoice_en.pdf'.format(order_info.order_code))
            return render(request, template_name=template, context=context)
    return HttpResponseRedirect(reverse('public'))


def order_production_list(request, order_public_access_key, pk):
    if pk:
        pk = int(str(pk).replace(',', ''))
    template = '{0}/order/order_production_list.html'.format(app_name)
    order_info = get_object_or_404(Order, pk=pk)
    if order_info:
        if order_info.order_key == order_public_access_key:
            order_item_list = list(ItemList.objects.filter(order=pk).order_by('order_index'))
            if request.GET.get('v') == 'pdf':
                return render_to_pdf_response(request, template_name=template,
                                              context={'order_info': order_info, 'item_list': order_item_list},
                                              filename='{0}_invoice_en.pdf'.format(order_info.order_code))
            return render(request, template_name=template,
                          context={'order_info': order_info, 'item_list': order_item_list})
        else:
            return HttpResponseRedirect(reverse('public'))
    else:
        return HttpResponseRedirect(reverse('public'))


class OrderListView(TechBrewListView):
    model = Order
    template_name_suffix = '/order_list'

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        d = self.request.GET.get('d')
        s = self.request.GET.get('s')
        e = self.request.GET.get('e')
        f = self.request.GET.get('f')
        object_list = Order.objects.all()
        if not self.request.user.has_perm('{0}.view_all_orders'.format(app_name)):
            object_list = object_list.filter(
                Q(created_by=self.request.user) | Q(
                    cooperators=self.request.user) | Q(order_state__can_view=True)).distinct()
        if c:
            object_list = object_list.filter(order_state_id=c)
        if f:
            object_list = object_list.filter(sub_company_id=f)
        if d:
            object_list = object_list.filter(created_by_id=d).order_by('-datetime_updated')
        if s:
            object_list = object_list.filter(order_create_date__gte=s)
        if e:
            object_list = object_list.filter(order_create_date__lte=e)
        if q:
            object_list = object_list.filter(Q(order_code__icontains=q) | Q(order_desc__icontains=q) | Q(
                client__name__icontains=q) | Q(client__company__icontains=q)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['order_states'] = OrderState.objects.all()
        context['sub_companies'] = SubCompany.objects.all()
        context['created_bys'] = User.objects.filter(Q(
            user_permissions__content_type__app_label=app_name) | Q(
            groups__permissions__content_type__app_label=app_name)).distinct().order_by('id')
        return context


class OrderSuccessListView(TechBrewListView):
    model = Order
    template_name_suffix = '/order_list'

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        d = self.request.GET.get('d')
        s = self.request.GET.get('s')
        e = self.request.GET.get('e')
        object_list = Order.objects.filter(order_state__is_confirmed=True)
        if not self.request.user.has_perm('{0}.view_all_orders'.format(app_name)):
            object_list = object_list.filter(
                Q(created_by=self.request.user) | Q(
                    cooperators=self.request.user) | Q(order_state__can_view=True)).distinct()
        if c:
            object_list = object_list.filter(order_state_id=c)
        if d:
            object_list = object_list.filter(created_by_id=d)
        if s:
            object_list = object_list.filter(order_create_date__gte=s)
        if e:
            object_list = object_list.filter(order_create_date__lte=e)
        if q:
            object_list = object_list.filter(Q(order_code__icontains=q) | Q(order_desc__icontains=q) | Q(
                client__name__icontains=q) | Q(client__company__icontains=q)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['created_bys'] = User.objects.filter(Q(
            user_permissions__content_type__app_label=app_name) | Q(
            groups__permissions__content_type__app_label=app_name)).distinct().order_by('id')
        return context


def equipments(request, is_part=True, title=''):
    template_name = '{0}/equipment/equipment_ls.html'.format(app_name)
    q = request.GET.get('q')
    c = request.GET.get('c')
    context = dict()
    object_list = Equipment.objects.filter(equipment_type__is_part=is_part).order_by('equipment_code')
    if c:
        object_list = object_list.filter(equipment_type_id=c)
    if q:
        object_list = object_list.filter(
            Q(equipment_code__icontains=q) | Q(equipment_cn__icontains=q) | Q(equipment_code_auto__icontains=q) | Q(
                equipment_en__icontains=q)).distinct()
    object_p_data = object_paginator(request, object_list)
    context['page_obj'] = object_p_data
    context['equipment_types'] = EquipmentType.objects.filter(is_part=is_part).all()
    context['title'] = title
    return render(request, template_name=template_name, context=context)


class EquipmentAllListView(TechBrewListView):
    model = Equipment
    template_name_suffix = '/equipment_ls'
    paginate_by = 50

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        object_list = Equipment.objects.order_by('-pk')
        if c:
            object_list = object_list.filter(equipment_type_id=c)
        if q:
            object_list = object_list.filter(
                Q(equipment_code__icontains=q) | Q(equipment_cn__icontains=q) | Q(equipment_code_auto__icontains=q) | Q(
                    equipment_en__icontains=q)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['equipment_types'] = EquipmentType.objects.all()
        context['title'] = _('设备列表')
        return context


@login_required
@permission_required('{0}.view_equipment'.format(app_name))
def equipment_ls(request):
    return equipments(request, is_part=False, title=_('设备列表'))


@login_required
@permission_required('{0}.view_equipment'.format(app_name))
def equipment_p_ls(request):
    return equipments(request, is_part=True, title=_('备件列表'))


class OrderDetailView(TechBrewDetailView):
    model = Order
    template_name_suffix = '/order_detail'

    def get_queryset(self):
        object_list = Order.objects.all()
        if not self.request.user.has_perm('{0}.view_all_orders'.format(app_name)):
            object_list = object_list.filter(
                Q(created_by=self.request.user) | Q(
                    cooperators=self.request.user) | Q(order_state__can_view=True)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['order_items'] = ItemList.objects.filter(order=self.object.pk).order_by('order_index')
        return context


class OrderCreate(TechBrewCreateView):
    model = Order
    form_class = OrderForm
    template_name_suffix = '/order_create'


class OrderUpdate(TechBrewUpdateView):
    model = Order
    form_class = OrderUpdateForm
    template_name_suffix = '/order_update'

    def get_queryset(self):
        object_list = Order.objects.all()
        if not self.request.user.has_perm('{0}.view_all_orders'.format(app_name)):
            object_list = object_list.filter(
                Q(created_by=self.request.user) | Q(
                    cooperators=self.request.user) | Q(order_state__can_view=True)).distinct()
        return object_list

    def form_valid(self, form):
        if form.is_valid:
            model = form.save(commit=False)
            if model.order_state.pk == 2:
                send_msg(model.salesman.name, model.order_code)
            model.save()
            if model:
                LogEntry.objects.log_action(
                    user_id=self.request.user.pk,
                    content_type_id=get_content_type_for_model(model).pk,
                    object_id=model.pk,
                    object_repr=str(model),
                    action_flag=CHANGE,
                )
        return super().form_valid(form)


class OrderFileUpdate(TechBrewUpdateView):
    model = Order
    form_class = OrderFileUpdateForm
    template_name_suffix = '/order_file_update'

    def get_queryset(self):
        object_list = Order.objects.all()
        if not self.request.user.has_perm('{0}.view_all_orders'.format(app_name)):
            object_list = object_list.filter(
                Q(created_by=self.request.user) | Q(
                    cooperators=self.request.user) | Q(order_state__can_view=True)).distinct()
        return object_list


class OrderEditorUpdate(TechBrewUpdateView):
    model = Order
    form_class = OrderEditorUpdateForm
    template_name_suffix = '/order_editor_update'

    def get_queryset(self):
        object_list = Order.objects.all()
        if not self.request.user.has_perm('{0}.view_all_orders'.format(app_name)):
            object_list = object_list.filter(
                Q(created_by=self.request.user) | Q(
                    cooperators=self.request.user) | Q(order_state__can_view=True)).distinct()
        return object_list


class EquipmentDetailView(TechBrewDetailView):
    model = Equipment
    template_name_suffix = '/equipment_detail'


class EquipmentDetailPublicView(DetailView):
    model = Equipment
    template_name_suffix = '/equipment_detail_public'


class EquipmentCreate(TechBrewCreateView):
    model = Equipment
    form_class = EquipmentForm
    template_name_suffix = '/equipment_create'


class EquipmentUpdate(TechBrewUpdateView):
    model = Equipment
    form_class = EquipmentUpdateForm
    template_name_suffix = '/equipment_update'


class EquipmentCopy(TechBrewUpdateView):
    model = Equipment
    form_class = EquipmentForm
    template_name_suffix = '/equipment_create'


class ItemListUpdate(TechBrewUpdateView):
    model = ItemList
    form_class = ItemListForm
    template_name_suffix = '/itemlist_update'


class ItemListNoteUpdate(TechBrewUpdateView):
    model = ItemList
    form_class = ItemListNoteUpdateForm
    template_name_suffix = '/itemlist_note_update'


class ClientListView(TechBrewListView):
    model = Client
    template_name_suffix = '/client_list'

    def get_queryset(self):
        q = self.request.GET.get('q')
        object_list = Client.objects.all()
        if q:
            object_list = object_list.filter(Q(name__icontains=q) | Q(company__icontains=q) | Q(
                post_address__icontains=q) | Q(company_address__icontains=q) | Q(desc__icontains=q)).distinct()
        return object_list


class ClientDetailView(DetailView):
    model = Client
    template_name_suffix = '/client_detail'


class ClientCreate(TechBrewCreateView):
    model = Client
    form_class = ClientForm
    template_name_suffix = '/client_create'


class ClientUpdate(TechBrewUpdateView):
    model = Client
    form_class = ClientForm
    template_name_suffix = '/client_update'


@login_required
@permission_required('{0}.change_order'.format(app_name))
def order_confirm(request, pk):
    if request:
        order_state_id = OrderState.objects.filter(is_confirmed=True).first()
        if order_state_id:
            related_order = Order.objects.get(pk=pk)
            if request.user.is_superuser or related_order.created_by_id == request.user.id:
                related_order.order_state_id = order_state_id
                related_order.save()
    return HttpResponseRedirect(reverse('{0}:order_detail'.format(app_name), args=[pk]))


@login_required
@permission_required('{0}.delete_itemlist'.format(app_name))
def delete_order_item(request, pk):
    if request:
        ojs = ItemList.objects.filter(pk=pk)
        if ojs.exists():
            oj = ojs.first()
            LogEntry.objects.log_action(
                user_id=request.user.pk,
                content_type_id=get_content_type_for_model(oj).pk,
                object_id=oj.pk,
                object_repr=str(oj),
                action_flag=DELETION,
            )
            order_id = oj.order.pk
            oj.delete()
            return HttpResponseRedirect(reverse('{0}:order_detail'.format(app_name), args=[order_id]))
    return HttpResponseRedirect(reverse('{0}:order_list'.format(app_name)))


class ServiceRecordListView(TechBrewListView):
    model = ServiceRecord
    template_name_suffix = '/servicerecord_list'

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        s = self.request.GET.get('s')
        e = self.request.GET.get('e')
        object_list = ServiceRecord.objects.all()
        if c:
            object_list = object_list.filter(service_state_id=c)
        if s:
            object_list = object_list.filter(datetime_created__gte=s)
        if e:
            object_list = object_list.filter(datetime_created__lte=e)
        if q:
            object_list = object_list.filter(Q(title__icontains=q) | Q(related_order__order_desc__icontains=q) | Q(
                related_order__order_code__icontains=q) | Q(remarks__icontains=q) | Q(
                related_order__client__name__icontains=q) | Q(related_order__client__mobile__icontains=q) | Q(
                salesman__name__icontains=q)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['service_states'] = ServiceState.objects.all()
        return context


class ServiceRecordDetailView(TechBrewDetailView):
    model = ServiceRecord
    template_name_suffix = '/servicerecord_detail'


class ServiceRecordCreate(TechBrewCreateView):
    model = ServiceRecord
    form_class = ServiceRecordForm
    template_name_suffix = '/servicerecord_create'
    permission_required = '{0}.add_servicerecord'.format(app_name)


class ServiceRecordUpdate(TechBrewUpdateView):
    model = ServiceRecord
    form_class = ServiceRecordForm
    template_name_suffix = '/servicerecord_update'


class AnnounceCreate(TechBrewCreateView):
    model = Announce
    form_class = AnnounceForm
    template_name_suffix = '/announce_create'


class AnnounceUpdate(TechBrewUpdateView):
    model = Announce
    form_class = AnnounceForm
    template_name_suffix = '/announce_update'


@login_required
@permission_required('{0}.add_itemlist'.format(app_name))
def add_order_items(request, pk):
    template = '{0}/itemlist/add_order_items.html'.format(app_name)
    ob = ItemListForm
    redirect_to = '{0}:order_detail'.format(app_name)
    selected_order = Order.objects.get(pk=pk)
    if request.method == 'POST':
        form = ob(request.POST)
        if form.is_valid():
            md = form.save()
            if md:
                LogEntry.objects.log_action(
                    user_id=request.user.pk,
                    content_type_id=get_content_type_for_model(md).pk,
                    object_id=md.pk,
                    object_repr=str(md),
                    action_flag=ADDITION,
                )
        elif form.errors:
            return render(request,
                          template_name=template,
                          context={'form': form,
                                   'select_order_id': selected_order.pk,
                                   'next_index': selected_order.next_index})
        return HttpResponseRedirect(reverse(redirect_to, args=[pk]))
    else:
        form = ob()
    return render(request,
                  template_name=template,
                  context={'form': form,
                           'select_order_id': selected_order.pk,
                           'next_index': selected_order.next_index})


@login_required
@permission_required('{0}.add_itemlist'.format(app_name))
def batch_add_order_items(request, order_id):
    template = '{0}/equipmentlist/batch_add_order_items.html'.format(app_name)
    redirect_to = '{0}:order_detail'.format(app_name)
    ob = BatchEquipmentAddForm
    equipment_list = EquipmentList.objects.all()
    if request.method == 'POST':
        form = ob(request.POST)
        if form.is_valid():
            sel = EquipmentList.objects.get(pk=form.cleaned_data['batch_equipment'])
            if sel:
                equipment_lists = sel.equipment_list
                for e in equipment_lists:
                    item = ItemList(order_index=e[0], equipment_id=e[1], amount=e[2], order_id=order_id,
                                    created_by_id=request.user.id)
                    item.save()
                    if item:
                        LogEntry.objects.log_action(
                            user_id=request.user.pk,
                            content_type_id=get_content_type_for_model(item).pk,
                            object_id=item.pk,
                            object_repr=str(item),
                            action_flag=ADDITION,
                        )
                return HttpResponseRedirect(reverse(redirect_to, args=[order_id]))
    else:
        form = ob()
    return render(request, template_name=template, context={'form': form,
                                                            'equipment_list': equipment_list,
                                                            'select_order_id': order_id})


class EquipmentListListView(TechBrewListView):
    model = EquipmentList
    template_name_suffix = '/batch_equipment_list'
    paginate_by = 10


@login_required
@permission_required('{0}.add_equipmentlist'.format(app_name))
def create_batch_equipment_list(request):
    ob = BatchEquipmentCreateForm
    redirect_to = '{0}:batch_equipment_list'.format(app_name)
    order_l = Order.objects.all()
    template = '{0}/equipmentlist/create_batch_equipment_list.html'.format(app_name)
    if request.method == 'POST':
        form = ob(request.POST)
        if form.is_valid():
            bel = list()
            unique_c = list()
            es = ItemList.objects.filter(order_id=form.cleaned_data['order_list']).order_by('order_index')
            for e in es:
                if e.equipment.pk not in unique_c:
                    unique_c.append(e.equipment.pk)
                    bel.append([e.order_index, e.equipment.pk, e.amount])
            eq_l_c = EquipmentList.objects.create(equipment_list=bel, title=form.cleaned_data['title'],)
            if eq_l_c:
                LogEntry.objects.log_action(
                    user_id=request.user.pk,
                    content_type_id=get_content_type_for_model(eq_l_c).pk,
                    object_id=eq_l_c.pk,
                    object_repr=str(eq_l_c),
                    action_flag=ADDITION,
                )
            return HttpResponseRedirect(reverse(redirect_to))
    else:
        form = ob()
    return render(request, template_name=template, context={'form': form, 'order_list': order_l})


class EquipmentListUpdate(TechBrewUpdateView):
    model = EquipmentList
    form_class = EquipmentListForm
    template_name_suffix = '/equipment_list_update'

    def form_valid(self, form):
        if form.is_valid:
            model = form.save(commit=False)
            # print(len(model.equipment_list))
            if len(model.equipment_list) % 3 == 0:
                # print(model.equipment_list)
                model.equipment_list = convert_list(model.equipment_list)
                # print(model.equipment_list)
                model.save()
                if model:
                    LogEntry.objects.log_action(
                        user_id=self.request.user.pk,
                        content_type_id=get_content_type_for_model(model).pk,
                        object_id=model.pk,
                        object_repr=str(model),
                        action_flag=CHANGE,
                    )
        return super().form_valid(form)


@login_required
def password_change_own(request):
    template_name = '{0}/user/password_change.html'.format(app_name)
    if request.user.is_authenticated:
        u = User.objects.get(id=request.user.id)
        form = PasswordChangeForm(u)
        if request.method == 'POST':
            form = PasswordChangeForm(u, request.POST)
            if form.is_valid():
                u.set_password(form.cleaned_data['new_password1'])
                u.save()
        return render(request, template_name=template_name, context={'form': form})
    else:
        return redirect('public')


class EquipmentPriceUpdate(TechBrewUpdateView):
    model = Equipment
    form_class = EquipmentPriceUpdateForm
    template_name_suffix = '/price_update'
    permission_required = '{0}.change_equipment_price'.format(app_name)


@login_required
@permission_required('{0}.view_all_orders'.format(app_name))
def user_action_list(request):
    template_name = '{0}/user/action_list.html'.format(app_name)
    context = dict()
    d = request.GET.get('d')
    s = request.GET.get('s')
    e = request.GET.get('e')
    q = request.GET.get('q')
    object_list = LogEntry.objects.filter(content_type__app_label=app_name)
    if d:
        object_list = object_list.filter(user_id=d)
    if s:
        object_list = object_list.filter(action_time__gte=s)
    if e:
        object_list = object_list.filter(action_time__lte=e)
    if q:
        object_list = object_list.filter(
            Q(object_repr__icontains=q) | Q(action_flag__icontains=q) | Q(
                change_message__icontains=q)).distinct()
    object_p_data = object_paginator(request, object_list)
    context['page_obj'] = object_p_data
    context['created_bys'] = User.objects.filter(Q(
        user_permissions__content_type__app_label=app_name) | Q(
        groups__permissions__content_type__app_label=app_name)).distinct().order_by('id')
    return render(request, template_name=template_name, context=context)


@login_required
@permission_required('{0}.add_salesman'.format(app_name))
def create_s_user(request):
    template_name = '{0}/user/user_list.html'.format(app_name)
    form = AuthenticationForm
    user_created = None
    permission = Permission.objects.get(
        codename='view_equipment',
        content_type=ContentType.objects.get_for_model(Equipment),
    )
    users_have = User.objects.filter(Q(
        user_permissions__content_type__app_label=app_name) | Q(
        groups__permissions__content_type__app_label=app_name)).filter(
        is_superuser=False).distinct().order_by('id')
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username and password:
            user_exist = User.objects.filter(username=username)
            if user_exist.exists():
                return render(request, template_name=template_name,
                              context={'form': form, 'user_exist': user_exist.first(), 'users_have': users_have})
            user_created = User.objects.create_user(username, '', password)
            user_created.user_permissions.add(permission)
            if user_created:
                LogEntry.objects.log_action(
                    user_id=request.user.pk,
                    content_type_id=get_content_type_for_model(user_created).pk,
                    object_id=user_created.pk,
                    object_repr=str(user_created),
                    action_flag=ADDITION,
                )
    return render(request, template_name=template_name,
                  context={'form': form, 'user_created': user_created, 'users_have': users_have})


class GroupCreate(TechBrewCreateView):
    model = Group
    form_class = GroupForm
    template_name_suffix = '/group_list'
    success_url = '/{0}/groups/'.format(app_name)
    permission_required = '{0}.add_salesman'.format(app_name)

    def get_template_names(self):
        names = list()
        names.append("{0}/{1}{2}.html".format(app_name, 'user', self.template_name_suffix))
        return names

    def get_context_data(self, **kwargs):
        context = super(GroupCreate, self).get_context_data(**kwargs)
        context['groups'] = Group.objects.filter(permissions__content_type__app_label=app_name).distinct()
        return context

    def form_valid(self, form):
        if form.is_valid:
            model = form.save(commit=False)
            if app_name not in model.name:
                model.name = '{0}-{1}'.format(app_name, model.name)
                while Group.objects.filter(name=model.name):
                    k = 1
                    model.name = '{0}({1})'.format(model.name, k)
                    k += 1
            model.save()
            if model:
                LogEntry.objects.log_action(
                    user_id=self.request.user.pk,
                    content_type_id=get_content_type_for_model(model).pk,
                    object_id=model.pk,
                    object_repr=str(model),
                    action_flag=ADDITION,
                )
        return super(GroupCreate, self).form_valid(form)


class UserUpdate(TechBrewUpdateView):
    model = User
    form_class = UserUpdateForm
    template_name_suffix = '/update_user'
    success_url = '/{0}/users/'.format(app_name)

    queryset = User.objects.filter(Q(
        user_permissions__content_type__app_label=app_name) | Q(
        groups__permissions__content_type__app_label=app_name)).filter(
        is_superuser=False).distinct().order_by('id')

    def get_template_names(self):
        names = list()
        names.append("{0}/{1}{2}.html".format(app_name, 'user', self.template_name_suffix))
        return names

    def form_valid(self, form):
        if form.is_valid:
            model = form.save(commit=False)
            model.save()
            if model:
                LogEntry.objects.log_action(
                    user_id=self.request.user.pk,
                    content_type_id=get_content_type_for_model(model).pk,
                    object_id=model.pk,
                    object_repr=str(model),
                    action_flag=CHANGE,
                )
        return super().form_valid(form)


class GroupUpdate(TechBrewUpdateView):
    model = Group
    form_class = GroupForm
    template_name_suffix = '/update_group'
    success_url = '/{0}/groups/'.format(app_name)

    queryset = Group.objects.filter(permissions__content_type__app_label=app_name).distinct().order_by('id')

    def get_template_names(self):
        names = list()
        names.append("{0}/{1}{2}.html".format(app_name, 'user', self.template_name_suffix))
        return names

    def form_valid(self, form):
        if form.is_valid:
            model = form.save(commit=False)
            if app_name not in model.name:
                model.name = '{0}-{1}'.format(app_name, model.name)
                while Group.objects.filter(name=model.name):
                    k = 1
                    model.name = '{0}({1})'.format(model.name, k)
                    k += 1
            model.save()
            if model:
                LogEntry.objects.log_action(
                    user_id=self.request.user.pk,
                    content_type_id=get_content_type_for_model(model).pk,
                    object_id=model.pk,
                    object_repr=str(model),
                    action_flag=CHANGE,
                )
        return super().form_valid(form)


class EquipmentInListView(TechBrewListView):
    model = EquipmentIn
    template_name_suffix = '/equipment_in'

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        d = self.request.GET.get('d')
        object_list = EquipmentIn.objects.all()
        if c and object_list:
            object_list = object_list.filter(warehouse_id=c)
        if d:
            object_list = object_list.filter(equipment__equipment_type__type_category=d)
        if q:
            object_list = object_list.filter(Q(
                equipment__equipment_code__icontains=q) | Q(
                equipment__equipment_en__icontains=q) | Q(
                equipment__equipment_cn__icontains=q)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['warehouse_ls'] = Warehouse.objects.all()
        context['type_categories'] = TypeCategory.objects.all()
        return context


class EquipmentOutListView(TechBrewListView):
    model = EquipmentOut
    template_name_suffix = '/equipment_out'

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        d = self.request.GET.get('d')
        object_list = EquipmentOut.objects.all()
        if c and object_list:
            object_list = object_list.filter(warehouse_id=c)
        if d:
            object_list = object_list.filter(equipment__equipment_type__type_category=d)
        if q:
            object_list = object_list.filter(Q(
                equipment__equipment_code__icontains=q) | Q(
                equipment__equipment_en__icontains=q) | Q(
                equipment__equipment_cn__icontains=q)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['warehouse_ls'] = Warehouse.objects.all()
        context['type_categories'] = TypeCategory.objects.all()
        return context


@login_required
@permission_required('{0}.view_equipmentin'.format(app_name))
def equipment_inventory(request):
    template_name = '{0}/equipmentin/equipment_inventory.html'.format(app_name)
    q = request.GET.get('q')
    c = request.GET.get('c')
    d = request.GET.get('d')
    object_list = EquipmentIn.objects.all()
    if c and object_list:
        object_list = object_list.filter(warehouse_id=c)
    if d:
        object_list = object_list.filter(equipment__equipment_type__type_category=d)
    if q:
        object_list = object_list.filter(Q(
            equipment__equipment_code__icontains=q) | Q(
            equipment__equipment_en__icontains=q) | Q(
            equipment__equipment_cn__icontains=q)).distinct()
    context = dict()
    equipment_in_l = object_list.values('equipment').annotate(total_in=Sum('amount')).order_by('total_in').distinct()
    e_l = list()
    if equipment_in_l:
        for e in equipment_in_l:
            e_d = e
            e_d['equipment'] = Equipment.objects.get(pk=e_d.get('equipment'))
            if c:
                e_out = EquipmentOut.objects.filter(warehouse_id=c)
            else:
                e_out = EquipmentOut.objects.all()
            total_out = e_out.filter(equipment_id=e.get('equipment')).aggregate(total_out=Sum('amount'))
            if total_out.get('total_out'):
                e_d['total_out'] = total_out.get('total_out')
            else:
                e_d['total_out'] = 0
            e_d['amount_left'] = e_d['total_in'] - e_d['total_out']
            e_l.append(e_d)
    object_p_data = object_paginator(request, e_l, per_page_count=20)
    context['page_obj'] = object_p_data
    context['warehouse_ls'] = Warehouse.objects.all()
    context['type_categories'] = TypeCategory.objects.all()
    return render(request, template_name=template_name, context=context)


class EquipmentInCreate(TechBrewCreateView):
    model = EquipmentIn
    form_class = EquipmentInForm
    template_name_suffix = '/equipment_in_create'
    permission_required = '{0}.add_equipmentin'.format(app_name)


class EquipmentInUpdate(TechBrewUpdateView):
    model = EquipmentIn
    form_class = EquipmentInUpdateForm
    template_name_suffix = '/equipment_in_update'


class EquipmentOutCreate(TechBrewCreateView):
    model = EquipmentOut
    form_class = EquipmentOutForm
    template_name_suffix = '/equipment_out_create'
    permission_required = '{0}.add_equipmentout'.format(app_name)


class EquipmentOutUpdate(TechBrewUpdateView):
    model = EquipmentOut
    form_class = EquipmentOutForm
    template_name_suffix = '/equipment_out_update'


class InOutListView(TechBrewListView):
    model = InOut
    template_name_suffix = '/in_out_list'

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        s = self.request.GET.get('s')
        e = self.request.GET.get('e')
        object_list = InOut.objects.all()
        if not self.request.user.is_superuser:
            object_list = object_list.filter(created_by=self.request.user)
        if c:
            object_list = object_list.filter(in_out_type_id=c)
        if s:
            object_list = object_list.filter(in_out_date__gte=s)
        if e:
            object_list = object_list.filter(in_out_date__lte=e)
        if q:
            object_list = object_list.filter(desc__icontains=q).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['in_out_types'] = InOutType.objects.all()
        io_per_month_column_data = io_per_month_column()
        context['in_out_month'] = json.dumps(io_per_month_column_data[0])
        context['income_info'] = json.dumps(io_per_month_column_data[1])
        context['outcome_info'] = json.dumps(io_per_month_column_data[2])
        context['io_come_info'] = json.dumps(io_per_month_column_data[3])
        context['total_income'] = io_per_month_column_data[4]
        context['total_outcome'] = io_per_month_column_data[5]
        context['outcome_by_types'] = json.dumps(outcome_by_types_pie())
        return context


class InOutCreate(TechBrewCreateView):
    model = InOut
    form_class = InOutForm
    template_name_suffix = '/add_inout'


class InOutUpdate(TechBrewUpdateView):
    model = InOut
    form_class = InOutUpdateForm
    template_name_suffix = '/change_inout'

    def get_queryset(self):
        object_list = InOut.objects.all()
        if not self.request.user.is_superuser:
            object_list = object_list.filter(created_by=self.request.user)
        return object_list


class InOutTypeListView(TechBrewListView):
    model = InOutType
    template_name_suffix = '/in_out_type_list'


class InOutTypeCreate(TechBrewCreateView):
    model = InOutType
    form_class = InOutTypeForm
    template_name_suffix = '/add_inouttype'


class InOutTypeUpdate(TechBrewUpdateView):
    model = InOutType
    form_class = InOutTypeForm
    template_name_suffix = '/change_inouttype'


class FixedAssetsListView(TechBrewListView):
    model = FixedAssets
    template_name_suffix = '/fixed_assets_list'

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        object_list = FixedAssets.objects.all()
        if c:
            object_list = object_list.filter(fixed_assets_type_id=c)
        if q:
            object_list = object_list.filter(Q(name_of_asset__icontains=q) | Q(specifications__icontains=q)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['fixed_assets_types'] = FixedAssetsType.objects.all()
        return context


class FixedAssetsCreate(TechBrewCreateView):
    model = FixedAssets
    form_class = FixedAssetsForm
    template_name_suffix = '/add_fixedassets'


class FixedAssetsUpdate(TechBrewUpdateView):
    model = FixedAssets
    form_class = FixedAssetsForm
    template_name_suffix = '/change_fixedassets'


class FixedAssetsTypeCreate(TechBrewCreateView):
    model = FixedAssetsType
    form_class = FixedAssetsTypeForm
    template_name_suffix = '/add_fixedassetstype'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['fixed_assets_types'] = FixedAssetsType.objects.all()
        return context


class FixedAssetsTypeUpdate(TechBrewUpdateView):
    model = FixedAssetsType
    form_class = FixedAssetsTypeForm
    template_name_suffix = '/change_fixedassetstype'


class FixedAssetsInListView(TechBrewListView):
    model = FixedAssetsIn
    template_name_suffix = '/fixed_assets_in_list'

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        object_list = FixedAssetsIn.objects.all()
        if c:
            object_list = object_list.filter(fixed_assets__fixed_assets_type_id=c)
        if q:
            object_list = object_list.filter(
                Q(fixed_assets__name_of_asset__icontains=q) | Q(fixed_assets__specifications__icontains=q)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['fixed_assets_types'] = FixedAssetsType.objects.all()
        return context


class FixedAssetsInCreate(TechBrewCreateView):
    model = FixedAssetsIn
    form_class = FixedAssetsInForm
    template_name_suffix = '/add_fixed_assets_in'


class FixedAssetsInUpdate(TechBrewUpdateView):
    model = FixedAssetsIn
    form_class = FixedAssetsInForm
    template_name_suffix = '/change_fixed_assets_in'


class FixedAssetsOutListView(TechBrewListView):
    model = FixedAssetsOut
    template_name_suffix = '/fixed_assets_out_list'

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        object_list = FixedAssetsOut.objects.all()
        if c:
            object_list = object_list.filter(fixed_assets__fixed_assets_type_id=c)
        if q:
            object_list = object_list.filter(
                Q(fixed_assets__name_of_asset__icontains=q) | Q(fixed_assets__specifications__icontains=q)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['fixed_assets_types'] = FixedAssetsType.objects.all()
        return context


class FixedAssetsOutCreate(TechBrewCreateView):
    model = FixedAssetsOut
    form_class = FixedAssetsOutForm
    template_name_suffix = '/add_fixed_assets_out'


class FixedAssetsOutUpdate(TechBrewUpdateView):
    model = FixedAssetsOut
    form_class = FixedAssetsOutForm
    template_name_suffix = '/change_fixed_assets_out'


class EquipmentAssemblyListView(TechBrewListView):
    model = EquipmentAssembly
    template_name_suffix = '/equipment_assembly_list'
    paginate_by = 10

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        object_list = EquipmentAssembly.objects.all()
        if not self.request.user.is_staff:
            object_list = object_list.filter(
                Q(created_by=self.request.user) | Q(cooperators=self.request.user)).distinct()
        if c:
            object_list = object_list.filter(equipment__equipment_type_id=c)
        if q:
            object_list = object_list.filter(Q(
                assembly_name__icontains=q) | Q(
                equipment__equipment_code__icontains=q) | Q(
                equipment__equipment_exp_code__icontains=q) | Q(
                equipment__equipment_en__icontains=q) | Q(
                equipment__equipment_cn__icontains=q)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['equipment_types'] = EquipmentType.objects.all()
        return context


class PlanAssemblyListView(TechBrewListView):
    model = PlanAssembly
    template_name_suffix = '/plan_assembly_list'
    paginate_by = 10

    def get_queryset(self):
        q = self.request.GET.get('q')
        c = self.request.GET.get('c')
        object_list = PlanAssembly.objects.all()
        if c:
            object_list = object_list.filter(related_equipment_assembly__equipment__equipment_type_id=c)
        if q:
            object_list = object_list.filter(Q(
                related_equipment_assembly__assembly_name__icontains=q) | Q(
                related_equipment_assembly__equipment__equipment_code__icontains=q) | Q(
                related_equipment_assembly__equipment__equipment_exp_code__icontains=q) | Q(
                related_equipment_assembly__equipment__equipment_en__icontains=q) | Q(
                related_equipment_assembly__equipment__equipment_cn__icontains=q)).distinct()
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['equipment_types'] = EquipmentType.objects.all()
        return context


@login_required
@permission_required('{0}.view_equipmentassembly'.format(app_name))
def equipment_assembly_detail(request, pk):
    if pk:
        pk = int(str(pk).replace(',', ''))
    assembly_info = get_object_or_404(EquipmentAssembly, pk=pk)
    is_editor = False
    if assembly_info.cooperators:
        if request.user in assembly_info.cooperators.all():
            is_editor = True
    if assembly_info:
        if request.user.is_staff or request.user == assembly_info.created_by or is_editor is True:
            return render(
                request,
                template_name='{0}/equipmentassembly/equipment_assembly_detail.html'.format(app_name),
                context={'object': assembly_info})
    return HttpResponseRedirect(reverse('{0}:equipment_assembly_list'.format(app_name)))


@login_required
@permission_required('{0}.view_planassembly'.format(app_name))
def plan_assembly_detail(request, pk):
    if pk:
        pk = int(str(pk).replace(',', ''))
    assembly_info = get_object_or_404(PlanAssembly, pk=pk)
    e_l = list()
    if assembly_info:
        if assembly_info.related_equipment_assembly:
            if assembly_info.related_equipment_assembly.assembly_list:
                for e_d in assembly_info.related_equipment_assembly.assembly_list:
                    e_d_n = dict()
                    e_d_n['order_index'] = e_d.order_index
                    e_d_n['equipment'] = e_d.equipment
                    e_d_n['amount_need_single'] = e_d.amount
                    e_d_n['amount_need_all'] = e_d.amount * assembly_info.amount
                    e_d_n['amount_left_all'] = e_d.equipment.amount_left['total']
                    e_d_n['amount_need_buy'] = e_d_n['amount_need_all'] - e_d_n['amount_left_all']
                    e_l.append(e_d_n)
        return render(
            request,
            template_name='{0}/planassembly/equipment_assembly_detail.html'.format(app_name),
            context={
                'object': assembly_info,
                'e_l': e_l,
                'current_date': timezone.localdate()
            })
    return HttpResponseRedirect(reverse('{0}:plan_assembly_list'.format(app_name)))


class EquipmentAssemblyCreate(TechBrewCreateView):
    model = EquipmentAssembly
    form_class = EquipmentAssemblyForm
    template_name_suffix = '/add_equipment_assembly'


class PlanAssemblyCreate(TechBrewCreateView):
    model = PlanAssembly
    form_class = PlanAssemblyForm
    template_name_suffix = '/add_plan_assembly'


class EquipmentAssemblyUpdate(TechBrewUpdateView):
    model = EquipmentAssembly
    form_class = EquipmentAssemblyUpdateForm
    template_name_suffix = '/change_equipment_assembly'


class PlanAssemblyUpdate(TechBrewUpdateView):
    model = PlanAssembly
    form_class = PlanAssemblyForm
    template_name_suffix = '/change_plan_assembly'


@login_required
@permission_required('{0}.delete_planassembly'.format(app_name))
def plan_assembly_delete(request, pk):
    if request:
        ojs = PlanAssembly.objects.filter(pk=pk)
        if ojs.exists():
            oj = ojs.first()
            LogEntry.objects.log_action(
                user_id=request.user.pk,
                content_type_id=get_content_type_for_model(oj).pk,
                object_id=oj.pk,
                object_repr=str(oj),
                action_flag=DELETION,
            )
            oj.delete()
    return HttpResponseRedirect(reverse('{0}:plan_assembly_list'.format(app_name)))


class AssemblyItemCreate(TechBrewCreateView):
    model = AssemblyItem
    form_class = AssemblyItemForm
    template_name_suffix = '/add_assembly_item'

    def get_context_data(self, **kwargs):
        context = super(self.__class__, self).get_context_data(**kwargs)
        context['object'] = None
        is_editor = False
        a = self.request.GET.get('a')
        if a:
            e_as = EquipmentAssembly.objects.filter(pk=a)
            if e_as.exists():
                e_a = e_as.first()
                if e_a.cooperators:
                    if self.request.user in e_a.cooperators.all():
                        is_editor = True
                if self.request.user == e_a.created_by or is_editor is True or self.request.user.is_staff:
                    context['object'] = e_a
        return context


class AssemblyItemUpdate(TechBrewUpdateView):
    model = AssemblyItem
    form_class = AssemblyItemUpdateForm
    template_name_suffix = '/change_assembly_item'


@login_required
@permission_required('{0}.delete_assemblyitem'.format(app_name))
def assembly_item_delete(request, pk):
    if request:
        ojs = AssemblyItem.objects.filter(pk=pk)
        if ojs.exists():
            oj = ojs.first()
            LogEntry.objects.log_action(
                user_id=request.user.pk,
                content_type_id=get_content_type_for_model(oj).pk,
                object_id=oj.pk,
                object_repr=str(oj),
                action_flag=DELETION,
            )
            oj.delete()
    return HttpResponseRedirect(reverse('{0}:equipment_assembly_list'.format(app_name)))


@login_required
@permission_required('{0}.view_equipment'.format(app_name))
def eq_ls(request):
    context = dict()
    if request:
        q = request.GET.get('q')
        if q:
            e_lsa = Equipment.objects.filter(Q(equipment_cn__icontains=q) | Q(equipment_en__icontains=q) | Q(
                equipment_code__icontains=q)).distinct()
        else:
            e_lsa = Equipment.objects.all()
        if e_lsa.exists():
            paginator = Paginator(e_lsa, 50)
        else:
            context['data'] = None
            context['has_next'] = False
            return HttpResponse(content=json.dumps(context), content_type="application/json", status=200)

        page = request.GET.get('page')
        e_ls = paginator.get_page(page)
        rsp = list()
        if e_ls:
            for e in e_ls:
                r = dict()
                r['pk'] = e.pk
                r['equipment_code'] = e.equipment_code
                r['equipment_cn'] = e.equipment_cn
                rsp.append(r)
        context['has_next'] = e_ls.has_next()
        context['data'] = rsp
        return HttpResponse(content=json.dumps(context), content_type="application/json", status=200)


def excel_export(request, file_name='test', model=None, list_obj=None, head=None, fields=None):
    if not request.user.is_authenticated:
        return HttpResponse(u'请登录！')
    if list_obj is None and model:
        list_obj = model.objects.all()
    if list_obj:
        ws = xlwt.Workbook(encoding='utf-8')
        w = ws.add_sheet(file_name)
        excel_row = 0
        k = 0
        if head:
            for h in head:
                w.write(excel_row, k, h)
                k += 1
        excel_row = 1
        k = 0
        for obj in list_obj:
            if fields:
                for d in fields:
                    v_list = d.split('__')
                    value = obj
                    for v in v_list:
                        if value:
                            value = getattr(value, v)
                    if value is None:
                        value = ''
                    if value is True:
                        value = '是'
                    if value is False:
                        value = '否'
                    w.write(excel_row, k, '{0}'.format(value),)
                    k += 1
            excel_row += 1
            k = 0
        bio = BytesIO()
        ws.save(bio)
        bio.seek(0)
        response = HttpResponse(bio.getvalue(), content_type='application/vnd.ms-excel')
        response['Content-Disposition'] = 'attachment; filename={0}.xls'.format(file_name)
        response.write(bio.getvalue())
        return response
    return HttpResponse('没有数据')


@login_required
@permission_required('{0}.change_equipemntassembly'.format(app_name))
@require_http_methods(["GET"])
def ea_export(request, pk):
    if request.user.is_staff or request.user.has_perm('{0}:view_all_orders'.format(app_name)):
        style = xlwt.XFStyle()  # 初始化样式
        font = xlwt.Font()  # 为样式创建字体
        borders = xlwt.Borders()
        alignment = xlwt.Alignment()
        borders.left = xlwt.Borders.THIN
        # May be: NO_LINE, THIN, MEDIUM, DASHED, DOTTED, THICK, DOUBLE, HAIR, MEDIUM_DASHED, THIN_DASH_DOTTED,
        # MEDIUM_DASH_DOTTED, THIN_DASH_DOT_DOTTED, MEDIUM_DASH_DOT_DOTTED,
        # SLANTED_MEDIUM_DASH_DOTTED, or 0x00 through 0x0D.
        borders.right = xlwt.Borders.THIN
        borders.top = xlwt.Borders.THIN
        borders.bottom = xlwt.Borders.THIN
        borders.left_colour = 0x40
        borders.right_colour = 0x40
        borders.top_colour = 0x40
        borders.bottom_colour = 0x40
        font.name = 'Times New Roman'
        alignment.horz = xlwt.Alignment.HORZ_JUSTIFIED
        alignment.wrap = xlwt.Alignment.WRAP_AT_RIGHT
        alignment.vert = xlwt.Alignment.VERT_JUSTIFIED
        style.font = font  # 设定样式
        style.borders = borders
        style.alignment = alignment
        #
        col_width = [5, 6, 12, 24, 24, 24, 12, 12, 8, 8, 12, 20]
        heads = ['No.', u'部件ID', u'产品编号', u'设备编号', u'部件中文名', u'部件英文名', u'部件类型',
                 u'价格', u'数量', u'库存', u'小计', u'备注']
        fields = ['', 'equipment_id', 'equipment__equipment_code_auto', 'equipment__equipment_code',
                  'equipment__equipment_cn', 'equipment__equipment_en', 'equipment__equipment_type',
                  'equipment__basic_price', 'amount', 'amount_left', 'total_value', 'notes']
        selected_eas = EquipmentAssembly.objects.filter(pk=pk)
        if selected_eas.exists():
            selected_ea = selected_eas.first()
            file_name = 'main-SBZZ-{0}-{1}'.format(selected_ea.pk, timezone.localdate())
            list_obj = AssemblyItem.objects.filter(equipment_assembly=selected_ea).order_by('order_index')
            if list_obj.exists():
                ws = xlwt.Workbook(encoding='utf-8')
                w = ws.add_sheet('Main_Equipment_{0}'.format(selected_ea.equipment.pk))
                excel_row = 0
                k = 0
                if heads:
                    for h in heads:
                        w.write(excel_row, k, h, style)
                        k += 1
                excel_row = 1
                k = 0
                for obj in list_obj:
                    if fields:
                        for d in fields:
                            if d:
                                if '__' in d:
                                    d_d = d.split('__')
                                    w.write(excel_row, k, '{0}'.format(getattr(getattr(obj, d_d[0]), d_d[1])), style)
                                else:
                                    w.write(excel_row, k, '{0}'.format(getattr(obj, d)), style)
                            else:
                                w.write(excel_row, k, '{0}'.format(excel_row), style)
                            k += 1
                    excel_row += 1
                    k = 0
                bio = BytesIO()
                # 设置列表宽度
                for i, width in enumerate(col_width):
                    w.col(i).width = 256 * width
                ws.save(bio)
                bio.seek(0)
                response = HttpResponse(bio.getvalue(), content_type='application/vnd.ms-excel')
                response['Content-Disposition'] = 'attachment; filename={0}.xls'.format(file_name)
                response.write(bio.getvalue())
                return response
    else:
        return HttpResponse('权限不够，找老板去！')


@login_required
@permission_required('{0}.change_inout'.format(app_name))
@require_http_methods(["GET"])
def money_io_export(request):
    s = request.GET.get('s')
    e = request.GET.get('e')
    model = InOut
    list_obj = None
    if validate_date(s):
        list_obj = model.objects.filter(money_in_out_date__gte=validate_date(s))
        if validate_date(e):
            list_obj = list_obj.filter(money_in_out_date__lte=validate_date(e))
    head = ['id', u'日期',  u'收支类型', u'金额', u'余额', u'备注', u'关联订单', u'经手人', u'已收款', u'创建时间', u'最后更新']
    fields = ['pk', 'in_out_date', 'in_out_type__in_out_type', 'amount', 'left_before',
              'desc', 'linked_order__order_code', 'created_by__username', 'is_confirmed', 'datetime_created', 'datetime_updated']
    return excel_export(request, file_name='money_in_out', model=model, list_obj=list_obj, head=head, fields=fields)